package com.leilei.sensitive;


import java.util.function.UnaryOperator;

/**
 * @author lei
 * @create 2024-05-20 14:26
 * @desc 脱敏替换枚举
 **/
public enum SensitiveReplaceEnum {


    /**
     * 默认实现，具体逻辑需要在调用时设置
     */
    CUSTOMER(origin -> desensitizeValue(origin, 0, 0, null)),
    /**
     * 用户名, 如: **梦
     */
    CHINESE_NAME(SensitiveReplaceEnum::chineseName),

    /**
     * 身份证号, 如: 110************234
     */
    ID_CARD(SensitiveReplaceEnum::idCardNum),

    /**
     * 座机号, 如: ****1234
     */
    FIXED_PHONE(SensitiveReplaceEnum::fixedPhone),

    /**
     * 手机号, 如: 176****1234
     */
    MOBILE_PHONE(SensitiveReplaceEnum::mobilePhone),

    /**
     * 地址, 如: 四川省成都市********
     */
    ADDRESS(SensitiveReplaceEnum::address),

    /**
     * 电子邮件, 如: s*****o@xx.com
     */
    EMAIL(SensitiveReplaceEnum::email),

    /**
     * 密码, 永远是 ******, 与长度无关
     */
    PASSWORD(SensitiveReplaceEnum::password),
    ;

    public static final String MASK_STR = SensitiveAutoConfiguration.maskStr;
    static final String DEFAULT_SENSITIVE_CHAR;

    static {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            builder.append(MASK_STR);
        }
        DEFAULT_SENSITIVE_CHAR = builder.toString();
    }


    private final UnaryOperator<String> desensitizeFunction;

    SensitiveReplaceEnum(UnaryOperator<String> desensitizeFunction) {
        this.desensitizeFunction = desensitizeFunction;
    }


    public String desensitize(String origin) {
        return desensitizeFunction.apply(origin);
    }

    /**
     * 脱敏实现，字符串替换
     *
     * @param originStr 原字符
     * @param prefix    保留前面位数
     * @param suffix    保留后面位数
     * @param maskStr   替换符
     * @return String
     * @author lei
     * @date 2024-05-20 11:41:02
     */
    public static String desensitizeValue(String originStr, Integer prefix, Integer suffix, String maskStr) {
        if (maskStr == null) {
            maskStr = MASK_STR;
        }
        if (originStr == null) {
            return null;
        }
        int length = originStr.length();
        if (prefix + suffix >= length) {
            // 如果前缀和后缀的长度之和大于或等于字符串的长度,固定加密为6个脱敏符
            return originStr.replace(originStr, DEFAULT_SENSITIVE_CHAR);
        }
        int maskedLength = length - prefix - suffix;
        // 强制最少添加两个遮掩字符
        if (maskedLength < SensitiveProperties.MIN_MSK_LENGTH) {
            maskedLength = SensitiveProperties.MIN_MSK_LENGTH;
        }
        StringBuilder sb = new StringBuilder();
        // 添加前缀部分
        sb.append(originStr, 0, prefix);
        // 添加中间的遮掩部分，这里考虑到逆脱敏必须填充指定长度的字符
        for (int i = 0; i < maskedLength; i++) {
            sb.append(maskStr);
        }
        // 添加后缀部分
        sb.append(originStr, length - suffix, length);
        return sb.toString();
    }


    /**
     * 【中文姓名】只显示最后一个汉字，其他隐藏为星号，比如：**梦
     */
    public static String chineseName(String fullName) {
        if (fullName == null) {
            return null;
        }
        return desensitizeValue(fullName, 0, 1, MASK_STR);
    }

    /**
     * 【身份证号】显示前3位后3,其他隐藏。共计18位或者15位，比如：340304*******1234
     */
    public static String idCardNum(String id) {
        return desensitizeValue(id, 3, 3, MASK_STR);
    }

    /**
     * 【固定电话】后四位，其他隐藏，比如 ****1234
     */
    public static String fixedPhone(String num) {
        return desensitizeValue(num, 0, 4, MASK_STR);
    }

    /**
     * 【手机号码】前三位，后四位，其他隐藏，比如135****810
     */
    public static String mobilePhone(String num) {
        return desensitizeValue(num, 3, 3, MASK_STR);
    }

    /**
     * 【地址】只显示到地区，不显示详细地址，比如：北京市海淀区****
     */
    public static String address(String address) {
        return desensitizeValue(address, 6, 0, MASK_STR);
    }

    /**
     * 【电子邮箱 邮箱前缀仅显示第一个字母，前缀其他隐藏，用星号代替，@及后面的地址显示，比如：d**@126.com
     */
    public static String email(String email) {
        if (email == null) {
            return null;
        }
        int index = email.indexOf('@');
        if (index <= 1) {
            return MASK_STR;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(email.charAt(0));
        for (int i = 1; i < index; i++) {
            sb.append(MASK_STR);
        }
        sb.append(email.substring(index));
        return sb.toString();

    }


    /**
     * 【密码】密码强制使用六星
     */
    public static String password(String password) {
        if (password == null) {
            return null;
        }
        return DEFAULT_SENSITIVE_CHAR;
    }

}
